import { _decorator, AudioClip, AudioSource, CCInteger, CircleCollider2D, Collider2D, Component, Contact2DType, director, instantiate, IPhysics2DContact, Label, Node, Prefab, RichText, UITransform, v2, v3, Vec3 } from 'cc';
import { Joystick } from './Joystick';
const { ccclass, property } = _decorator;

@ccclass('Head')
export class Head extends Component {
    //#region 预制体引用
    @property(Prefab)
    public bodyPrefab: Prefab = null;//蛇身预制体
    @property(Prefab)
    public foodPrefab: Prefab = null;//食物预制体
    //#endregion

    //#region 变量
    @property(Array(Node))
    public bodyArray: Node[] = [];//蛇身数组（包括头部）
    @property(CCInteger)
    bodyNum: number = 2;//初始蛇身数量
    @property(CCInteger)
    bodyDistance: number = 50;//蛇身距离
    speed: number = 200;//蛇移动速度
    @property(Vec3)
    SnakeDir: Vec3;//蛇头的方向
    previousMoveDir: Vec3//保存上一帧的移动方向
    @property
    Score: number = 0;
    @property(AudioClip)
    public eatSound: AudioClip = null;
    @property(AudioClip)
    public dieSound: AudioClip = null;
    //#endregion

    //#region UI
    @property(RichText)
    public txt_Score: RichText = null;
    @property(Node)
    public startPanel: Node = null;
    @property(Node)
    public gameOverPanel: Node = null;
    @property(Node)
    public joystick: Node;
    //#endregion


    protected onLoad(): void {

        this.previousMoveDir = this.node.position.clone().normalize();
        this.bodyArray.push(this.node);//获取身体
        this.rotateHead(this.node.position);//头部转动

        for (let i = 1; i <= this.bodyNum; i++) {
            this.getNewBody();
        }
        this.node.setPosition(this.randomPos());//头部随机出现
    }

    start() {
        if (!director.isPaused()) {
            director.pause();
        }
        this.node.parent.addChild(instantiate(this.foodPrefab));
        this.schedule(function () {
            this.moveBody();
        }, 0.2);

        let collider = this.node.getComponent(Collider2D);
        collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
    }

    update(deltaTime: number) {
        this.SnakeDir = this.joystick.getComponent(Joystick).dir.normalize();//让蛇的方向为遥感的方向
        if (this.SnakeDir.length() == 0) {
            this.SnakeDir = this.previousMoveDir.clone().normalize();
        }
        else {
            this.node.angle = this.joystick.getComponent(Joystick).calculateAngle() - 90;
            this.previousMoveDir = this.SnakeDir;
        }
        let newPos = this.node.position.clone().add(this.SnakeDir.clone().multiplyScalar(this.speed * deltaTime));//蛇以当前获取的方向不断移动
        this.node.setPosition(newPos);
    }

    //初始化蛇身和增加蛇身的方法
    getNewBody() {
        let newBody = instantiate(this.bodyPrefab);
        if (this.bodyArray.length < 3)//如果蛇身为1，只有蛇头的时候
        {
            let dir = this.node.position.clone().normalize();
            newBody.setPosition(this.node.position.clone().subtract(dir.multiplyScalar(this.bodyDistance)));
        }
        else {
            let lastBody = this.bodyArray[this.bodyArray.length - 1];
            let lastBody2 = this.bodyArray[this.bodyArray.length - 2];
            let dir = lastBody2.position.clone().subtract(lastBody.position).normalize();
            newBody.setPosition(lastBody.position.clone().subtract(dir.multiplyScalar(this.bodyDistance)));
            newBody.getComponent(Collider2D).group = 16;
        }
        //将实例化的色蛇身放入画布
        this.node.parent.addChild(newBody);
        //将新蛇身放入数组
        this.bodyArray.push(newBody);
        this.changZIndex();
    }



    //旋转蛇头
    rotateHead(headPos) {
        let angle = v2(1, 0).signAngle(headPos) * 180 / Math.PI;
        this.node.angle = angle - 90;
    }

    moveBody() {
        let headPos = this.node.position;//保存蛇头运动前的位置
        for (let i = this.bodyArray.length - 2; i >= 0; i--)//从后往前遍历蛇身
        {
            this.bodyArray[i + 1].position = this.bodyArray[i].position;//每一个蛇身都移动到它前面一个节点的位置
        }
        this.bodyArray[1].position = headPos;
    }

    //随机蛇生成的位置
    randomPos() {
        let width = this.node.parent.getComponent(UITransform).contentSize.width - 200;
        let height = this.node.parent.getComponent(UITransform).contentSize.height - 200;
        let x = Math.round(Math.random() * width) - width / 2;
        let y = Math.round(Math.random() * height) - height / 2;
        return v3(x, y, 0);
    }

    //设置蛇头的层级显示
    changZIndex() {
        let lastIndex = this.node.parent.children.length - 1;//最后一个子节点
        for (let i = 0; i < this.bodyArray.length; i++) {
            this.bodyArray[i].setSiblingIndex(lastIndex - i);
        }
    }

    startGame() {
        if (director.isPaused) {
            director.resume();
        }
        this.startPanel.active = false;
    }

    restartGame() {
        director.resume();
        director.loadScene("Game");
    }

    onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D) {
        //只在两个碰撞体开始接触时被调用一次
        if (otherCollider.group == 4) {
            otherCollider.node.removeFromParent();
            this.node.getComponent(AudioSource).playOneShot(this.eatSound);
            this.Score++;
            //右上角得分显示
            this.txt_Score.string = "<color=#000000>" + this.Score.toString() + "</color>";
            //产生食物
            let newFood = instantiate(this.foodPrefab);
            this.node.parent.addChild(newFood);
            //更新身体
            this.getNewBody();
        }
        if (otherCollider.group == 8 || otherCollider.group == 16) {
            this.node.getComponent(AudioSource).playOneShot(this.dieSound);
            this.gameOverPanel.active = true;
            this.gameOverPanel.getChildByName("Txt_Score").getComponent(Label).string = "得分:" + this.Score.toString();
            director.pause();
        }
    }
}